Objective-C --- 分类和扩展

谈谈 OC 中的 Category 和 Extension

一.给类添加属性

1.成员变量与属性

二者最大的区别就是:成员变量仅供内部使用,属性可供外部使用;

很多人在学到Category时都会有疑问,既然允许用Category给类增加方法和属性,那为什么不允许增加成员变量?

在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,但是文档中特别说明:

This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.

这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就被runtime加载,没有机会调用addIvar。程序在运行时动态构建的类需要在调用objc_registerClassPair之后才可以被使用,同样没有机会再添加成员变量。

那为什么runtime允许动态添加方法和属性,而不会引发问题呢?

因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。

那么由此分类的作用与局限便清晰了,以下做个总结。
作用:
1.分类可以在不获悉,不改变原来代码的情况下往里面添加新的方法,但不能添加实例变量
2.如果分类和原来类中的方法产生名称冲突,则分类将覆盖原来的方法,因为分类具有更高的优先级